package BeatBox;

import java.io.*;
import java.net.*;
import java.util.*;
import java.awt.*;
import javax.swing.*;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import java.awt.event.*;

public class VerySimpleChatServer 
{
	
	JFrame theFrame = new JFrame();
		JPanel onePanel = new JPanel();
			JTextArea incoming;
		JPanel twoPanel = new JPanel();
			JTextField PortText;
			JButton setPort = new JButton("Set Port");

	int port = 4242;

	ArrayList<PrintWriter> clientOutputStreams;
	ArrayList<ObjectOutputStream> clientObjectOutputStreams;
	public static void main(String[] args) 
	{
		VerySimpleChatServer server = new VerySimpleChatServer();
		server.buildGui();	
	}
	
	private void buildGui() 
	{
		incoming = new JTextArea(15,50);
		incoming.setLineWrap(true);//设置文本区的换行策略。如果设置为 true，则当行的长度大于所分配的宽度时，将换行。
		incoming.setWrapStyleWord(true);
		//设置换行方式（如果文本区要换行）。如果设置为 true，则当行的长度大于所分配的宽度时，将在单词边界（空白）处换行。
		incoming.setEditable(false);//设置指定的 boolean 变量，以指示此 TextComponent 是否应该为可编辑的。
		JScrollPane qScroller = new JScrollPane(incoming);
		qScroller.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);//确定垂直滚动条何时显示在滚动窗格上。
		qScroller.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);//确定水平滚动条何时显示在滚动窗格上。

		PortText = new JTextField(""+port,10);
		setPort.addActionListener(new MySetPortListener());

		onePanel.add(qScroller);
		twoPanel.add(PortText);
		twoPanel.add(setPort);
		theFrame.getContentPane().add(BorderLayout.CENTER,onePanel);
		theFrame.getContentPane().add(BorderLayout.SOUTH,twoPanel);
		theFrame.setBounds(499,271,538,360);
		theFrame.setVisible(true);
		theFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		PortText.selectAll();
		PortText.requestFocus();
	}
	
	public void setLink() 
	{
		new Thread
		(
			new Runnable()
			{
				public void run() 
				{
					clientOutputStreams = new ArrayList<PrintWriter>();
					clientObjectOutputStreams = new ArrayList<ObjectOutputStream>();
					try {
						@SuppressWarnings("all")
						ServerSocket serverSocket1 = new ServerSocket(port);
						@SuppressWarnings("all")
						ServerSocket serverSocket2 = new ServerSocket(port+1);			
						incoming.append("端口已设置为:"+port+"\n");
						while(true) {
							Socket clientSocket1 = serverSocket1.accept();
							PrintWriter writer = new PrintWriter(clientSocket1.getOutputStream());
							clientOutputStreams.add(writer);  
							Thread t1 = new Thread(new ClientHandler1(clientSocket1));
							t1.start();

							Socket clientSocket2 = serverSocket2.accept();
							ObjectOutputStream oStream = new ObjectOutputStream(clientSocket2.getOutputStream());
							clientObjectOutputStreams.add(oStream);  
							Thread t2 = new Thread(new ClientHandler2(clientSocket2));
							t2.start();
							
							System.out.println("got a connection");
						}
					}catch(Exception ex) {
						incoming.append("端口:"+port+"无法使用\n");
						ex.printStackTrace();
					}
				}
			}
		){}.start();
	}

	public void tellEveryone(String message) 
	{
		
		Iterator<PrintWriter> it = clientOutputStreams.iterator();//返回以恰当顺序在此列表的元素上进行迭代的迭代器。

		while(it.hasNext()) {//boolean hasNext()如果仍有元素可以迭代，则返回 true。
			try {
				PrintWriter writer = (PrintWriter) it.next();//next()返回迭代的下一个元素。
				writer.println(message);
				writer.flush();
			}catch(Exception ex) {
				ex.printStackTrace();
			}
		}
	}

	public void tellEveryone(boolean[] checkboxState)
	{
		Iterator<ObjectOutputStream> it = clientObjectOutputStreams.iterator();//返回以恰当顺序在此列表的元素上进行迭代的迭代器。

		while(it.hasNext()) {//boolean hasNext()如果仍有元素可以迭代，则返回 true。
			try {
				ObjectOutputStream oStream = (ObjectOutputStream) it.next();//next()返回迭代的下一个元素。
				oStream.writeObject(checkboxState);
				// oStream.writeObject(null);
				// oStream.flush();
				
			}catch(Exception ex) {
				ex.printStackTrace();
			}
		}
		tellEveryone("分享节奏已更新，点击listen即可听取");
	}

	public class ClientHandler1 implements Runnable 
	{
		
		BufferedReader reader;
		Socket sock;
		
		public ClientHandler1(Socket clientSocket) 
		{
			try {
				sock = clientSocket;
				InputStreamReader isReader = new InputStreamReader(sock.getInputStream());
				reader = new BufferedReader(isReader);
			}catch(Exception ex) {
				ex.printStackTrace();
			}
		}
		
		public void run() 
		{
			String message;
			try {
				while((message = reader.readLine()) != null) {
					System.out.println("read "+message);
					incoming.append("read "+message+"\n");
					incoming.selectAll();
					tellEveryone(message);
				}
			}catch(Exception ex) {
				ex.printStackTrace();
			}
		}
	}

	public class ClientHandler2 implements Runnable 
	{
		
		Socket sock;
		ObjectInputStream ois;
		public ClientHandler2(Socket clientSocket) 
		{
			try {
				sock = clientSocket;
				ois = new ObjectInputStream(new BufferedInputStream(sock.getInputStream()));
			}catch(Exception ex) {
				ex.printStackTrace();
			}
		}
		public void run() 
		{
			boolean[] checkboxState;
			try {
				while((checkboxState = (boolean[])ois.readObject()) != null) 
				{	
					tellEveryone(checkboxState);
				}
			}catch(Exception ex) {
				ex.printStackTrace();
			}
		}
	}

	public class MySetPortListener implements ActionListener
	{
		public void actionPerformed(ActionEvent e) 
		{
			port =Integer.parseInt( PortText.getText());
	 		setLink();
		}
	}
}
